
Aloísio Vítor
Image Processing Expert
TLDR: Esta guía muestra cómo combinar Botasaurus, un marco de raspado de web en Python con funciones de anti-detección integradas, y CapSolver, una API de resolución de CAPTCHA, para evitar automáticamente reCAPTCHA v2, reCAPTCHA v3 y Cloudflare Turnstile durante el raspado a gran escala. El proceso principal implica configurar el entorno, usar la extensión de navegador de CapSolver para identificar los parámetros de CAPTCHA, llamar a la API de CapSolver mediante una función de ayuda en Python para obtener un token de solución y finalmente usar Botasaurus para inyectar el token en la página web para el envío de formulario.

El raspado de web a gran escala suele encontrar CAPTCHAs que bloquean el acceso automatizado. Esta guía muestra cómo combinar Botasaurus, un marco poderoso de raspado de web, con CapSolver para resolver automáticamente los CAPTCHAs de reCAPTCHA v2, reCAPTCHA v3 y Cloudflare Turnstile.
Botasaurus es un marco de raspado de web en Python que simplifica la automatización del navegador con funciones de anti-detección integradas. Proporciona una API basada en decoradores limpia para tareas de navegador.
Características principales:
@browserInstalación:
pip install botasaurus
Uso básico:
from botasaurus.browser import browser, Driver
@browser()
def scrape_page(driver: Driver, data):
driver.get("https://example.com")
title = driver.get_text("h1")
return {"title": title}
# Ejecutar el raspador
result = scrape_page()
CapSolver es un servicio de resolución de CAPTCHA que proporciona una API para resolver varios tipos de CAPTCHA, incluyendo reCAPTCHA y Cloudflare Turnstile.
Tipos de CAPTCHA compatibles:
Obtener su clave de API:
CAP-)pip install botasaurus capsolver requests python-dotenv
Cree un archivo .env en la raíz de su proyecto:
CAPSOLVER_API_KEY=CAP-YOUR_API_KEY_HERE
Cree un cargador de configuración compartido:
# shared/config.py
import os
from pathlib import Path
from dotenv import load_dotenv
# Cargar el archivo .env desde la raíz del proyecto
ROOT_DIR = Path(__file__).parent.parent
load_dotenv(ROOT_DIR / ".env")
class Config:
"""Clase de configuración para la integración de CapSolver."""
# Clave de API de CapSolver
CAPSOLVER_API_KEY: str = os.getenv("CAPSOLVER_API_KEY", "")
# Endpoints de la API de CapSolver
CAPSOLVER_API_URL = "https://api.capsolver.com"
CREATE_TASK_ENDPOINT = f"{CAPSOLVER_API_URL}/createTask"
GET_RESULT_ENDPOINT = f"{CAPSOLVER_API_URL}/getTaskResult"
@classmethod
def validate(cls) -> bool:
"""Verificar si la configuración es válida."""
if not cls.CAPSOLVER_API_KEY:
print("Error: CAPSOLVER_API_KEY no está definido!")
return False
return True
Antes de integrar con la API, necesita identificar los parámetros correctos para el CAPTCHA objetivo. La extensión de navegador de CapSolver proporciona una forma sencilla de detectar automáticamente todos los parámetros necesarios.
Instale la extensión CapSolver desde la Chrome Web Store.
Importante: No cierre el panel de CapSolver antes de activar el CAPTCHA, ya que cerrarlo borra la información previamente detectada.
La extensión identifica automáticamente todos los parámetros necesarios de reCAPTCHA:
El detector proporciona una salida JSON formateada lista para la integración con la API, facilitando copiar los parámetros exactos necesarios para sus tareas de resolución.
Para más detalles, consulte la guía completa sobre identificación de parámetros de CAPTCHA.
reCAPTCHA v2 es el clásico CAPTCHA de casilla "No soy un robot". Puede presentar desafíos de selección de imágenes a los usuarios.
Puede usar el detector de extensión de CapSolver (descrito anteriormente) o encontrar la clave del sitio manualmente:
Busque en el HTML de la página:
<div class="g-recaptcha" data-sitekey="6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"></div>
O en JavaScript:
grecaptcha.render('container', {'sitekey': '6Le-xxxxx...'});
# utils/capsolver_helper.py
import time
import requests
from shared.config import Config
def solve_recaptcha_v2(
website_url: str,
website_key: str,
is_invisible: bool = False,
timeout: int = 120
) -> dict:
"""
Resolver reCAPTCHA v2 usando la API de CapSolver.
Args:
website_url: La URL de la página con el CAPTCHA
website_key: La clave del sitio de reCAPTCHA
is_invisible: Si es reCAPTCHA v2 invisible
timeout: Tiempo máximo para esperar la solución (segundos)
Returns:
diccionario con el token 'gRecaptchaResponse'
"""
if not Config.validate():
raise Exception("Configuración inválida - verifique su clave de API")
# Construir el payload de la tarea
task = {
"type": "ReCaptchaV2TaskProxyLess",
"websiteURL": website_url,
"websiteKey": website_key,
}
if is_invisible:
task["isInvisible"] = True
payload = {
"clientKey": Config.CAPSOLVER_API_KEY,
"task": task
}
# Crear la tarea
response = requests.post(Config.CREATE_TASK_ENDPOINT, json=payload)
result = response.json()
if result.get("errorId") and result.get("errorId") != 0:
raise Exception(f"Fallo al crear la tarea: {result.get('errorDescription')}")
task_id = result.get("taskId")
# Esperar resultado
start_time = time.time()
while time.time() - start_time < timeout:
time.sleep(2)
result_payload = {
"clientKey": Config.CAPSOLVER_API_KEY,
"taskId": task_id
}
response = requests.post(Config.GET_RESULT_ENDPOINT, json=result_payload)
result = response.json()
if result.get("status") == "ready":
return result.get("solution", {})
elif result.get("status") == "failed":
raise Exception(f"Tarea fallida: {result.get('errorDescription')}")
raise Exception(f"Tiempo de espera agotado después de {timeout} segundos")
from botasaurus.browser import browser, Driver
from shared.config import Config
from utils.capsolver_helper import solve_recaptcha_v2
DEMO_URL = "https://www.google.com/recaptcha/api2/demo"
DEMO_SITEKEY = "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-"
@browser(headless=False)
def solve_recaptcha_v2_with_api(driver: Driver, data: dict):
"""Resolver reCAPTCHA v2 usando la API de CapSolver e inyectar el token."""
url = data.get("url", DEMO_URL)
site_key = data.get("site_key", DEMO_SITEKEY)
# Paso 1: Cargar la página
driver.get(url)
driver.sleep(2)
# Paso 2: Extraer la clave del sitio de la página (opcional)
extracted_key = driver.run_js("""
const recaptchaDiv = document.querySelector('.g-recaptcha');
return recaptchaDiv ? recaptchaDiv.getAttribute('data-sitekey') : null;
""")
if extracted_key:
site_key = extracted_key
# Paso 3: Resolver el CAPTCHA usando la API de CapSolver
solution = solve_recaptcha_v2(
website_url=url,
website_key=site_key
)
token = solution.get("gRecaptchaResponse")
# Paso 4: Inyectar el token en la página
driver.run_js(f"""
// Establecer el valor del campo de texto oculto
const responseField = document.querySelector('[name="g-recaptcha-response"]');
if (responseField) {{
responseField.value = "{token}";
}}
// Activar el callback si está disponible
if (typeof ___grecaptcha_cfg !== 'undefined') {{
try {{
const clients = ___grecaptcha_cfg.clients;
for (const key in clients) {{
const client = clients[key];
if (client && client.callback) {{
client.callback("{token}");
}}
}}
}} catch (e) {{}}
}}
""")
# Paso 5: Enviar el formulario
submit_button = driver.select('input[type="submit"]')
if submit_button:
submit_button.click()
driver.sleep(2)
return {"success": True, "token_length": len(token)}
# Ejecutar el demo
result = solve_recaptcha_v2_with_api(data={"url": DEMO_URL, "site_key": DEMO_SITEKEY})
reCAPTCHA v3 es invisible y funciona analizando el comportamiento del usuario para generar una puntuación de 0.0 a 1.0.
Diferencia clave con v2: reCAPTCHA v3 requiere un parámetro pageAction.
La forma más fácil de encontrar pageAction es usando el detector de CAPTCHA de CapSolver. Alternativamente, busque en el JavaScript de la página:
grecaptcha.execute('siteKey', {action: 'login'})
// 'login' es su pageAction
def solve_recaptcha_v3(
website_url: str,
website_key: str,
page_action: str,
timeout: int = 120
) -> dict:
"""
Resolver reCAPTCHA v3 usando la API de CapSolver.
Args:
website_url: La URL de la página con el CAPTCHA
website_key: La clave del sitio de reCAPTCHA
page_action: El parámetro de acción (REQUERIDO para v3)
timeout: Tiempo máximo para esperar la solución (segundos)
Returns:
diccionario con el token 'gRecaptchaResponse'
"""
if not Config.validate():
raise Exception("Configuración inválida - verifique su clave de API")
if not page_action:
raise Exception("pageAction es REQUERIDO para reCAPTCHA v3")
# Construir el payload de la tarea
task = {
"type": "ReCaptchaV3TaskProxyLess",
"websiteURL": website_url,
"websiteKey": website_key,
"pageAction": page_action, # REQUERIDO para v3
}
payload = {
"clientKey": Config.CAPSOLVER_API_KEY,
"task": task
}
# Crear la tarea
response = requests.post(Config.CREATE_TASK_ENDPOINT, json=payload)
result = response.json()
if result.get("errorId") and result.get("errorId") != 0:
raise Exception(f"Fallo al crear la tarea: {result.get('errorDescription')}")
task_id = result.get("taskId")
# Esperar resultado
start_time = time.time()
while time.time() - start_time < timeout:
time.sleep(2)
result_payload = {
"clientKey": Config.CAPSOLVER_API_KEY,
"taskId": task_id
}
response = requests.post(Config.GET_RESULT_ENDPOINT, json=result_payload)
result = response.json()
if result.get("status") == "ready":
return result.get("solution", {})
elif result.get("status") == "failed":
raise Exception(f"Tarea fallida: {result.get('errorDescription')}")
raise Exception(f"Tiempo de espera agotado después de {timeout} segundos")
from botasaurus.browser import browser, Driver
from shared.config import Config
from utils.capsolver_helper import solve_recaptcha_v3
DEMO_URL = "https://recaptcha-demo.appspot.com/recaptcha-v3-request-scores.php"
DEMO_SITEKEY = "6LdyC2cUAAAAACGuDKpXeDorzUDWXmdqeg-xy696"
PAGE_ACTION = "examples/v3scores"
@browser(headless=False)
def solve_recaptcha_v3_with_api(driver: Driver, data: dict):
"""Resolver reCAPTCHA v3 usando la API de CapSolver e inyectar el token."""
url = data.get("url", DEMO_URL)
site_key = data.get("site_key", DEMO_SITEKEY)
page_action = data.get("page_action", PAGE_ACTION)
# Paso 1: Cargar la página
driver.get(url)
driver.sleep(2)
# Paso 2: Resolver el CAPTCHA usando la API de CapSolver
solution = solve_recaptcha_v3(
website_url=url,
website_key=site_key,
page_action=page_action
)
token = solution.get("gRecaptchaResponse")
# Paso 3: Inyectar el token en la página
driver.run_js(f"""
const token = "{token}";
// Establecer campo oculto si existe
const responseField = document.querySelector('[name="g-recaptcha-response"]');
if (responseField) {{
responseField.value = token;
}}
// Crear campo oculto si el formulario existe pero el campo no
const forms = document.querySelectorAll('form');
forms.forEach(form => {{
let field = form.querySelector('[name="g-recaptcha-response"]');
if (!field) {{
field = document.createElement('input');
field.type = 'hidden';
field.name = 'g-recaptcha-response';
form.appendChild(field);
}}
field.value = token;
}});
""")
# Paso 4: Enviar o verificar
buttons = driver.select_all("button")
for button in buttons:
if "verify" in button.text.lower() or "submit" in button.text.lower():
button.click()
driver.sleep(2)
break
return {"success": True, "token_length": len(token)}
# Ejecutar el demo
result = solve_recaptcha_v3_with_api(data={
"url": DEMO_URL,
"site_key": DEMO_SITEKEY,
"page_action": PAGE_ACTION
})
Cloudflare Turnstile es una alternativa de CAPTCHA centrada en la privacidad diseñada para ser menos intrusiva que los CAPTCHAs tradicionales.
Diferencias clave con reCAPTCHA:
AntiTurnstileTaskProxyLesstoken (no gRecaptchaResponse)0x4Busque en el HTML de la página:
<div class="cf-turnstile" data-sitekey="0x4AAAAAAABS7vwvV6VFfMcD"></div>
def solve_turnstile(
website_url: str,
website_key: str,
action: str = None,
cdata: str = None,
timeout: int = 120
) -> dict:
"""
Resolver Cloudflare Turnstile utilizando la API de CapSolver.
Args:
website_url: La URL de la página con Turnstile
website_key: La clave del sitio Turnstile (comienza con 0x4)
action: Acción opcional del atributo data-action
cdata: Cdata opcional del atributo data-cdata
timeout: Tiempo máximo para esperar la solución (segundos)
Returns:
diccionario con el campo 'token'
"""
if not Config.validate():
raise Exception("Configuración inválida - verifique su clave de API")
# Construir el cuerpo de la tarea
tarea = {
"type": "AntiTurnstileTaskProxyLess",
"websiteURL": website_url,
"websiteKey": website_key,
}
# Agregar metadatos opcionales
metadata = {}
if action:
metadata["action"] = action
if cdata:
metadata["cdata"] = cdata
if metadata:
tarea["metadata"] = metadata
payload = {
"clientKey": Config.CAPSOLVER_API_KEY,
"task": tarea
}
# Crear tarea
response = requests.post(Config.CREATE_TASK_ENDPOINT, json=payload)
result = response.json()
if result.get("errorId") and result.get("errorId") != 0:
raise Exception(f"Fallo al crear la tarea: {result.get('errorDescription')}")
task_id = result.get("taskId")
# Consultar resultados
start_time = time.time()
while time.time() - start_time < timeout:
time.sleep(2)
result_payload = {
"clientKey": Config.CAPSOLVER_API_KEY,
"taskId": task_id
}
response = requests.post(Config.GET_RESULT_ENDPOINT, json=result_payload)
result = response.json()
if result.get("status") == "ready":
return result.get("solution", {})
elif result.get("status") == "failed":
raise Exception(f"Tarea fallida: {result.get('errorDescription')}")
raise Exception(f"Tiempo de espera agotado después de {timeout} segundos")
from botasaurus.browser import browser, Driver
from shared.config import Config
from utils.capsolver_helper import solve_turnstile
DEMO_URL = "https://peet.ws/turnstile-test/non-interactive.html"
DEMO_SITEKEY = "0x4AAAAAAABS7vwvV6VFfMcD"
@browser(headless=False)
def solve_turnstile_with_api(driver: Driver, data: dict):
"""Resolver Cloudflare Turnstile utilizando la API de CapSolver e inyectar el token."""
url = data.get("url", DEMO_URL)
site_key = data.get("site_key", DEMO_SITEKEY)
# Paso 1: Cargar la página
driver.get(url)
driver.sleep(3)
# Paso 2: Extraer clave del sitio de la página (opcional)
extracted_params = driver.run_js("""
const turnstileDiv = document.querySelector('.cf-turnstile, [data-sitekey]');
if (turnstileDiv) {
const key = turnstileDiv.getAttribute('data-sitekey');
if (key && key.startsWith('0x')) {
return {
sitekey: key,
action: turnstileDiv.getAttribute('data-action')
};
}
}
return null;
""")
if extracted_params and extracted_params.get("sitekey"):
site_key = extracted_params["sitekey"]
# Paso 3: Resolver Turnstile mediante la API de CapSolver
solution = solve_turnstile(
website_url=url,
website_key=site_key,
action=extracted_params.get("action") if extracted_params else None
)
token = solution.get("token")
# Paso 4: Inyectar el token en la página
driver.run_js(f"""
const token = "{token}";
// Encontrar y llenar el campo cf-turnstile-response
const responseFields = [
document.querySelector('[name="cf-turnstile-response"]'),
document.querySelector('[name="cf_turnstile_response"]'),
document.querySelector('input[name*="turnstile"]')
];
for (const field of responseFields) {{
if (field) {{
field.value = token;
break;
}}
}}
// Crear campo oculto si existe el formulario pero no el campo
const forms = document.querySelectorAll('form');
forms.forEach(form => {{
let field = form.querySelector('[name="cf-turnstile-response"]');
if (!field) {{
field = document.createElement('input');
field.type = 'hidden';
field.name = 'cf-turnstile-response';
form.appendChild(field);
}}
field.value = token;
}});
""")
# Paso 5: Enviar el formulario
submit_btn = driver.select('button[type="submit"], input[type="submit"]')
if submit_btn:
submit_btn.click()
driver.sleep(2)
return {"success": True, "token_length": len(token)}
# Ejecutar el ejemplo
result = solve_turnstile_with_api(data={"url": DEMO_URL, "site_key": DEMO_SITEKEY})
| Tipo de Captcha | Tipo de Tarea | Campo de Respuesta | Parámetros Requeridos |
|---|---|---|---|
| reCAPTCHA v2 | ReCaptchaV2TaskProxyLess |
gRecaptchaResponse |
websiteURL, websiteKey |
| reCAPTCHA v2 Enterprise | ReCaptchaV2EnterpriseTaskProxyLess |
gRecaptchaResponse |
websiteURL, websiteKey |
| reCAPTCHA v3 | ReCaptchaV3TaskProxyLess |
gRecaptchaResponse |
websiteURL, websiteKey, pageAction |
| reCAPTCHA v3 Enterprise | ReCaptchaV3EnterpriseTaskProxyLess |
gRecaptchaResponse |
websiteURL, websiteKey, pageAction |
| Cloudflare Turnstile | AntiTurnstileTaskProxyLess |
token |
websiteURL, websiteKey |
Para sitios que bloquean IPs de centros de datos, utilice las variantes con proxy (por ejemplo, ReCaptchaV2Task) y proporcione su propio proxy residencial.
1. Expiración del Token
Los tokens de captcha expiran rápidamente (generalmente en 2 minutos). Siempre use el token inmediatamente después de recibirlo:
# Obtener token
solution = solve_recaptcha_v2(url, site_key)
token = solution.get("gRecaptchaResponse")
# Usar inmediatamente - no lo almacene para más tarde
driver.run_js(f'document.querySelector("[name=g-recaptcha-response]").value = "{token}"')
driver.select('button[type="submit"]').click()
2. Manejo de Errores
Siempre implemente un manejo adecuado de errores para fallas en la API:
try:
solution = solve_recaptcha_v2(url, site_key)
except Exception as e:
print(f"Fallo al resolver captcha: {e}")
# Implementar lógica de reintentos o alternativa
3. Límites de Velocidad
Agregue retrasos entre las solicitudes para evitar activar medidas anti-bot:
driver.sleep(2) # Esperar después de cargar la página
# ... resolver captcha ...
driver.sleep(1) # Esperar antes del envío del formulario
4. Validar Configuración
Siempre valide su clave de API antes de realizar solicitudes:
if not Config.validate():
raise Exception("Por favor, configure su clave de API en el archivo .env")
Combinar Botasaurus con CapSolver proporciona una solución sólida para manejar captchas en proyectos de raspado web. El enfoque basado en API le da control total sobre el proceso de resolución y funciona de manera confiable en diferentes tipos de captcha.
Aumente su presupuesto de automatización instantáneamente!
Use el código de bonificación CAPN al recargar su cuenta de CapSolver para obtener un 5% adicional en cada recarga — sin límites.
Canjéalo ahora en tu Panel de CapSolver
websiteURL y websiteKeypageActiontoken en lugar de gRecaptchaResponseEl método más efectivo es utilizar un framework de automatización de navegador robusto como Botasaurus, que maneja anti-detección, e integrarlo con una API dedicada para resolver captchas como CapSolver para obtener de forma programática los tokens necesarios.
Botasaurus simplifica la automatización de navegadores con una API basada en decoradores limpia, mientras que proporciona funciones esenciales de stealth para minimizar el riesgo de ser detectado y bloqueado por los sitios objetivo.
Aunque ambos requieren los parámetros websiteURL y websiteKey, resolver reCAPTCHA v3 (la versión invisible basada en puntuación) requiere adicionalmente un parámetro pageAction incluido en el cuerpo de la tarea enviado a la API de CapSolver.
Una vez que se recibe el token (por ejemplo, gRecaptchaResponse o token), debe inyectarse inmediatamente en el campo oculto de la página web objetivo mediante un comando de ejecución de JavaScript antes de que el formulario se envíe correctamente al servidor.
Los tokens de solución proporcionados por CapSolver para reCAPTCHA y Turnstile tienen un período de validez muy corto, expirando generalmente en aproximadamente 2 minutos, lo que requiere su uso inmediato.
Aprende una arquitectura de raspado web escalable en Rust con reqwest, scraper, raspado asíncrono, raspado con navegador sin cabeza, rotación de proxies y manejo de CAPTCHA conforme.

Automatiza la resolución de CAPTCHA con Nanobot y CapSolver. Utiliza Playwright para resolver reCAPTCHA y Cloudflare autónomamente.
